package br.com.gp.gerentes;

import java.util.List;
import org.hibernate.Hibernate;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import br.com.gp.anotation.Consulta;
import br.com.gp.anotation.SaveOrUpdate;
import br.com.gp.excecoes.ExceptionApplication;
import br.com.gp.excecoes.ExceptionValidador;
import br.com.gp.hibernate.HibernateUtilitario;

public class GerentePadraoImpl implements GerentePadrao{

	private HibernateUtilitario hib;
	private Session session;
	private Transaction transacao;

	@SaveOrUpdate(valida=true)
	public void incluir(Object obj) throws ExceptionApplication,
	ExceptionValidador {
		// TODO Auto-generated method stub
		try{
			getSession().save(obj);
			this.comit();
		}catch (HibernateException e) {
			// TODO: handle exception
			System.out.print(e);
			this.rowback();
			this.close();
			throw new ExceptionApplication("Erro ao tentar persistir o objeto",e);   

		}
	}

	@SaveOrUpdate(valida=true)
	public void alterar(Object obj) throws ExceptionApplication,
	ExceptionValidador {
		// TODO Auto-generated method stub
		try{
			getSession().saveOrUpdate(obj);
			this.comit();
		}catch (HibernateException e) {
			// TODO: handle exception
			System.out.print(e);
			this.rowback();
			this.close();
			throw new ExceptionApplication("Erro ao tentar persistir o objeto",e);   

		}
	}

	@SaveOrUpdate(valida=false)
	public void deletar(Object obj) throws ExceptionApplication {
		// TODO Auto-generated method stub
		try{
			getSession().delete(obj);
			this.comit();
		}catch (HibernateException e) {
			// TODO: handle exception
			System.out.print(e);
			this.rowback();
			this.close();
			throw new ExceptionApplication("Erro ao tentar persistir o objeto",e);   
		}
	}

	@SuppressWarnings("rawtypes")
	@Consulta
	public List obterListaEntidade(Class classe, Object obj)
	throws ExceptionApplication {
		// TODO Auto-generated method stub
		try {
			GerenteHQL gerente = new GerenteHQLImpl();
			return gerente.getQuery(classe, obj);
		} catch (ExceptionApplication e) {
			// TODO Auto-generated catch block
			System.out.print(e);
			throw new ExceptionApplication(e.getMessage());
		}catch (HibernateException e) {
			// TODO: handle exception
			System.out.print(e);
			this.close();
			throw new ExceptionApplication("Erro ao tentar persistir o objeto",e);   
		}
	}

	@SuppressWarnings("rawtypes")
	@Consulta
	public List obterListaEntidade(Class classe, Object obj, String ordenador)
	throws ExceptionApplication {
		// TODO Auto-generated method stub
		try {
			GerenteHQL gerente = new GerenteHQLImpl();
			return gerente.getQuery(classe, obj,ordenador);
		} catch (ExceptionApplication e) {
			// TODO Auto-generated catch block
			System.out.print(e);
			throw new ExceptionApplication(e.getMessage());
		}catch (HibernateException e) {
			// TODO: handle exception
			System.out.print(e);
			this.close();
			throw new ExceptionApplication("Erro ao tentar persistir o objeto",e);   
		}
	}

	@SuppressWarnings("rawtypes")
	@Consulta
	public List obterListaEntidade(Class classe, Object obj,
			Integer quantMaxResult) throws ExceptionApplication {
		// TODO Auto-generated method stub
		try {
			GerenteHQL gerente = new GerenteHQLImpl();
			return gerente.getQuery(classe, obj,quantMaxResult);
		} catch (ExceptionApplication e) {
			// TODO Auto-generated catch block
			System.out.print(e);
			throw new ExceptionApplication(e.getMessage());
		}catch (HibernateException e) {
			// TODO: handle exception
			this.close();
			throw new ExceptionApplication("Erro ao tentar persistir o objeto",e);   
		}
	}

	@SuppressWarnings("rawtypes")
	@Consulta
	public List obterListaEntidade(Class classe, Object obj, String ordenador,
			Integer quantMaxResult) throws ExceptionApplication {
		// TODO Auto-generated method stub
		try {
			GerenteHQL gerente = new GerenteHQLImpl();
			return gerente.getQuery(classe, obj,ordenador,quantMaxResult);
		} catch (ExceptionApplication e) {
			// TODO Auto-generated catch block
			System.out.print(e);
			throw new ExceptionApplication(e.getMessage());
		}catch (HibernateException e) {
			// TODO: handle exception
			System.out.print(e);
			this.close();
			throw new ExceptionApplication("Erro ao tentar persistir o objeto",e);   
		}
	}

	@SuppressWarnings("rawtypes")
	@Consulta
	public Object obterEntidadeForId(Class obj, Integer id)
	throws ExceptionApplication {
		// TODO Auto-generated method stub
		try{
			Object query = getSession().load(obj, id);
			Hibernate.initialize(query);
			return query;
		}catch (HibernateException e) {
			// TODO: handle exception
			System.out.print(e);
			this.close();
			
			throw new ExceptionApplication("Erro ao tentar persistir o objeto",e);   
		}
	}
	
	public static <T> List<T> listAndCast(Query q) {
	    @SuppressWarnings("unchecked")
	    List<T> list = q.list();
	    return list;
	}
	
	public HibernateUtilitario getHib() {
		return hib;
	}
	
	public void setHib(HibernateUtilitario hib) {
		this.hib = hib;
	}
	
	@SuppressWarnings("static-access")
	public Session getSession() {
		if(session ==null  || !session.isOpen()){
			setSession(hib.getSessionFactory().openSession());
		}
		return session;
	}
	
	public void setSession(Session session) {
		this.session = session;
	}
	
	public Transaction getTransacao() {
		setTransacao(getSession().beginTransaction());
		return transacao;
	}
	
	public void setTransacao(Transaction transacao) {
		this.transacao = transacao;
	}
	
	public void comit(){
		getTransacao().commit();
	}
	
	public void rowback(){
		getTransacao().rollback();
	}
	
	public void close(){
		getSession().close();
	}
}